﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using JBeamLibrary.Tools;
using JBeamLibrary.VehicleParts.Collections;
using JBeamLibrary.VehicleParts.Elements;
using JBeamLibrary.VehicleParts.Interfaces;

namespace JBeamLibrary.VehicleParts.Groups
{
    public class Hydros : IVehicleGroup<Hydro>
    {
        #region Fields

        private readonly Dictionary<int, long> _beamSpringList = new Dictionary<int, long>();
        private readonly Dictionary<int, long> _beamDampList = new Dictionary<int, long>();
        private readonly Dictionary<int, long> _beamDeformList = new Dictionary<int, long>();
        private readonly Dictionary<int, long> _beamStrengthList = new Dictionary<int, long>();
        private readonly Dictionary<int, float> _beamPrecompressionList = new Dictionary<int, float>();
        private readonly Dictionary<int, float> _beamLongBoundList = new Dictionary<int, float>();
        private readonly Dictionary<int, float> _beamShortBoundList = new Dictionary<int, float>();
        private readonly Dictionary<int, long> _beamLimitSpringList = new Dictionary<int, long>();
        private readonly Dictionary<int, long> _beamLimitDampList = new Dictionary<int, long>();
        private readonly Dictionary<int, BeamType> _beamTypeList = new Dictionary<int, BeamType>();
        private readonly Dictionary<int, string> _breakGroupList = new Dictionary<int, string>();
        private readonly Dictionary<int, string> _deformGroupList = new Dictionary<int, string>();
        private readonly HydroCollection _collection = new HydroCollection();

        #endregion

        #region Indexers

        /// <summary>Gets the hydro at the specified index</summary>
        /// <param name="index"></param>
        /// <returns></returns>
        public Hydro this[int index]
        {
            get
            {
                if (Collection.Count == 0)
                    return null;
                if (index < 0 || index >= Collection.Count)
                    return null;
                return Collection[index];
            }
        }

        /// <summary>Gets the hydro with the specified IDs</summary>
        /// <param name="id1"></param>
        /// /// <param name="id2"></param>
        /// <returns></returns>
        public Hydro this[string id1, string id2]
        {
            get { return Collection.FirstOrDefault(hydro => hydro.NodeId1.Equals(id1) && hydro.NodeId2.Equals(id2)); }
        }

        #endregion

        #region Properties

        public bool IsEmpty
        {
            get
            {
                return GroupHelper.GetPropertyLists(this).All(list => list.Count == 0) && Collection.Count == 0;
            }
        }

        public Dictionary<int, long> BeamSpringList
        {
            get { return _beamSpringList; }
        }

        public Dictionary<int, long> BeamDampList
        {
            get { return _beamDampList; }
        }

        public Dictionary<int, long> BeamDeformList
        {
            get { return _beamDeformList; }
        }

        public Dictionary<int, long> BeamStrengthList
        {
            get { return _beamStrengthList; }
        }

        public Dictionary<int, float> BeamPrecompressionList
        {
            get { return _beamPrecompressionList; }
        }

        public Dictionary<int, float> BeamLongBoundList
        {
            get { return _beamLongBoundList; }
        }

        public Dictionary<int, float> BeamShortBoundList
        {
            get { return _beamShortBoundList; }
        }

        public Dictionary<int, long> BeamLimitSpringList
        {
            get { return _beamLimitSpringList; }
        }

        public Dictionary<int, long> BeamLimitDampList
        {
            get { return _beamLimitDampList; }
        }

        public Dictionary<int, BeamType> BeamTypeList
        {
            get { return _beamTypeList; }
        }

        public Dictionary<int, string> BreakGroupList
        {
            get { return _breakGroupList; }
        }

        public Dictionary<int, string> DeformGroupList
        {
            get { return _deformGroupList; }
        }

        public HydroCollection Collection
        {
            get { return _collection; }
        }

        public IVehicleGroupCollection<Hydro> GroupCollection
        {
            get { return Collection; }
        }

        public int Count
        {
            get { return _collection.Count; }
        }

        #endregion

        #region Methods

        public void SetElementValue(int index, string propName, object value)
        {
            var elem = Collection[index];
            var prop = elem.GetType().GetProperty(propName);
            var type = prop.PropertyType;
            prop.SetValue(elem, Convert.ChangeType(value, type));
        }

        public object GetElementValue(int index, string propName)
        {
            var elem = Collection[index];
            var prop = elem.GetType().GetProperty(propName);
            return prop.GetValue(elem);
        }

        public IEnumerable<KeyValuePair<string, object>> GetElementValues(int index)
        {
            var elem = Collection[index];
            var props = elem.GetType().GetProperties();
            return props.Select(prop => new KeyValuePair<string, object>(prop.Name, prop.GetValue(elem))).AsEnumerable();
        }

        #endregion
    }
}
